/**
 * Copyright (c) 2021 Wei-Lun Hsu. All Rights Reserved.
 */
/** @file zb32l03x_hal_dma.h
 *
 * @author Wei-Lun Hsu
 * @version 0.1
 * @date 2021/09/27
 * @license
 * @description
 */

#ifndef __ZB32L03x_HAL_DMA_H
#define __ZB32L03x_HAL_DMA_H

#ifdef __cplusplus
extern "C" {
#endif

#include "zb32l03x_hal_def.h"

/** @addtogroup ZB32L03x_HAL_Driver
  * @{
  */

/** @addtogroup DMA
  * @{
  */
//=============================================================================
//                  Constant Definition
//=============================================================================
#define DMA_CHANNEL_MAX             16
#define HAL_DMA_IRQn                PDMA_IRQn

/** @defgroup DMA_Exported_Constants DMA Exported Constants
  * @{
  */

typedef enum HAL_DMA_Channel
{
    HAL_DMA_CHANNEL_00    = (0x1ul << 0),
    HAL_DMA_CHANNEL_01    = (0x1ul << 1),
    HAL_DMA_CHANNEL_02    = (0x1ul << 2),
    HAL_DMA_CHANNEL_03    = (0x1ul << 3),
    HAL_DMA_CHANNEL_04    = (0x1ul << 4),
    HAL_DMA_CHANNEL_05    = (0x1ul << 5),
    HAL_DMA_CHANNEL_06    = (0x1ul << 6),
    HAL_DMA_CHANNEL_07    = (0x1ul << 7),
    HAL_DMA_CHANNEL_08    = (0x1ul << 8),
    HAL_DMA_CHANNEL_09    = (0x1ul << 9),
    HAL_DMA_CHANNEL_10    = (0x1ul << 10),
    HAL_DMA_CHANNEL_11    = (0x1ul << 11),
    HAL_DMA_CHANNEL_12    = (0x1ul << 12),
    HAL_DMA_CHANNEL_13    = (0x1ul << 13),
    HAL_DMA_CHANNEL_14    = (0x1ul << 14),
    HAL_DMA_CHANNEL_15    = (0x1ul << 15),

    // CHSELREQ[C] = 0
    HAL_DMA_CHANNEL_ADC         = HAL_DMA_CHANNEL_00,
    HAL_DMA_CHANNEL_TIM2        = HAL_DMA_CHANNEL_01,
    HAL_DMA_CHANNEL_TIM2A       = HAL_DMA_CHANNEL_02,
    HAL_DMA_CHANNEL_QSPI_RXTX   = HAL_DMA_CHANNEL_03,
    HAL_DMA_CHANNEL_TIM2B       = HAL_DMA_CHANNEL_04,
    HAL_DMA_CHANNEL_SPI_I2S_RX  = HAL_DMA_CHANNEL_05,
    HAL_DMA_CHANNEL_SPI_I2S_TX  = HAL_DMA_CHANNEL_06,
    HAL_DMA_CHANNEL_USART2_RX   = HAL_DMA_CHANNEL_07,
    HAL_DMA_CHANNEL_USART2_TX   = HAL_DMA_CHANNEL_08,
    HAL_DMA_CHANNEL_USART3_RX   = HAL_DMA_CHANNEL_09,
    HAL_DMA_CHANNEL_USART3_TX   = HAL_DMA_CHANNEL_10,
    HAL_DMA_CHANNEL_I2C0_RX     = HAL_DMA_CHANNEL_11,
    HAL_DMA_CHANNEL_I2C0_TX     = HAL_DMA_CHANNEL_12,
    HAL_DMA_CHANNEL_TIM1        = HAL_DMA_CHANNEL_13,
    HAL_DMA_CHANNEL_TIM1A       = HAL_DMA_CHANNEL_14,
    HAL_DMA_CHANNEL_TIM1B       = HAL_DMA_CHANNEL_15,

    // CHSELREQ[C] = 1
    HAL_DMA_CHANNEL_AES_RX     = HAL_DMA_CHANNEL_02,
    HAL_DMA_CHANNEL_AES_TX     = HAL_DMA_CHANNEL_04,
    HAL_DMA_CHANNEL_LPUART_RX  = HAL_DMA_CHANNEL_09,
    HAL_DMA_CHANNEL_LPUART_TX  = HAL_DMA_CHANNEL_10,
    HAL_DMA_CHANNEL_TIM10      = HAL_DMA_CHANNEL_11,
    HAL_DMA_CHANNEL_TIM11      = HAL_DMA_CHANNEL_12,
    HAL_DMA_CHANNEL_LPTIM      = HAL_DMA_CHANNEL_13,
    HAL_DMA_CHANNEL_TIM10_ALT  = HAL_DMA_CHANNEL_14,    /**< The alternate channel of TIM10 */
    HAL_DMA_CHANNEL_TIM11_ALT  = HAL_DMA_CHANNEL_15,    /**< The alternate channel of TIM11 */

} HAL_DMA_Channel_TypeDef;

/**
 *   uDMA PL230 Arbitrate rate
 */
typedef enum DMA_Arbitration_Rate
{
    DMA_ARBITRATION_RATE_1      = 0x00,  /**< Arbitrate after each transfer */
    DMA_ARBITRATION_RATE_2      = 0x01,  /**< Arbitrate after every 2 transfers */
    DMA_ARBITRATION_RATE_4      = 0x02,  /**< Arbitrate after every 4 transfers */
    DMA_ARBITRATION_RATE_8      = 0x03,  /**< Arbitrate after every 8 transfers */
    DMA_ARBITRATION_RATE_16     = 0x04,  /**< Arbitrate after every 16 transfers */
    DMA_ARBITRATION_RATE_32     = 0x05,  /**< Arbitrate after every 32 transfers */
    DMA_ARBITRATION_RATE_64     = 0x06,  /**< Arbitrate after every 64 transfers */
    DMA_ARBITRATION_RATE_128    = 0x07,  /**< Arbitrate after every 128 transfers */
    DMA_ARBITRATION_RATE_256    = 0x08,  /**< Arbitrate after every 256 transfers */
    DMA_ARBITRATION_RATE_512    = 0x09,  /**< Arbitrate after every 512 transfers */
    DMA_ARBITRATION_RATE_1024   = 0x0a,  /**< Arbitrate after every 1024 transfers */

} DMA_Arbitration_Rate_t;

/**
 *   DMA transfer unit size
 */
typedef enum DMA_Data_Size
{
    DMA_DATA_SIZE_BYTE       = 0x00,          /**< Byte/8-bit data size */
    DMA_DATA_SIZE_HALFWORD   = 0x01,          /**< Half word/16-bit data size */
    DMA_DATA_SIZE_WORD       = 0x02,          /**< Word/32-bit data size */
    DMA_DATA_SIZE_RESVD      = 0x03,          /**< Reserved */
} DMA_Data_Size_t;


/**
 *  Address increment size after transferring
 */
typedef enum DMA_Data_Inc
{
    DMA_DATA_INC_BYTE       = 0x00,          /**< Byte/8-bit increment */
    DMA_DATA_INC_HALFWORD   = 0x01,          /**< Half word/16-bit increment */
    DMA_DATA_INC_WORD       = 0x02,          /**< Word/32-bit increment */
    DMA_DATA_INC_NONE       = 0x03,          /**< No increment */
} DMA_Data_Inc_t;

/**
 *  uDMA PL230 state
 */
typedef enum DMA_State
{
    DMA_STATE_IDLE      = 0,            /*!< idle                                  */
    DMA_STATE_READ_CHNNL_CTRL_DATA,     /*!< reading channel controller data       */
    DMA_STATE_READ_SRC_END_ADDR,        /*!< reading source data end pointer       */
    DMA_STATE_READ_DST_END_ADDR,        /*!< reading destination data end pointer  */
    DMA_STATE_READ_SRC_DATA,            /*!< reading source data                   */
    DMA_STATE_WRITE_DST_DATA,           /*!< writing destination data              */
    DMA_STATE_WAIT_REQ_CLR,             /*!< waiting for DMA request to clear      */
    DMA_STATE_WAIT_CHNNL_CTRL_DATA,     /*!< writing channel controller data       */
    DMA_STATE_STALLED,                  /*!< stalled                               */
    DMA_STATE_DONE,                     /*!< done                                  */
    DMA_STATE_PERI_SG_XFER,             /*!< peripheral scatter-gather transition  */

} DMA_State_t;

typedef enum DMA_Descriptor_Type
{
    DMA_DESCRIPTOR_TYPE_PRIMARY     = 0,
    DMA_DESCRIPTOR_TYPE_ALTERNATE,
    DMA_DESCRIPTOR_TYPE_USER,
} DMA_Descriptor_Type_t;

typedef enum
{
    HAL_DMA_STATE_RESET         = 0x00U,    /*!< DMA not yet initialized or disabled  */
    HAL_DMA_STATE_READY         = 0x01U,    /*!< DMA Initialized and ready for use    */
    HAL_DMA_STATE_BUSY          = 0x02U,    /*!< An internal process is ongoing       */
    HAL_DMA_STATE_TIMEOUT       = 0x03U,    /*!< Timeout state                        */
    HAL_DMA_STATE_ERROR         = 0x04U     /*!< Reception process is ongoing         */
} HAL_DMA_State_TypeDef;


typedef enum HAL_DMA_Mode
{
    HAL_DMA_Mode_STOP       = 0,
    HAL_DMA_MODE_BASIC,
    HAL_DMA_MODE_AUTO,
    HAL_DMA_MODE_PING_PONG,
    HAL_DMA_MODE_SG,                /**!< Scatter-gather */
    HAL_DMA_MODE_PERI_SG,           /**!< Peripheral Scatter-gather */

} HAL_DMA_Mode_TypeDef;

/**
  * @}
  */ /* End of group DMA_Exported_Constants */


//=============================================================================
//                  Structure Definition
//=============================================================================
/** @defgroup DMA_Exported_Types DMA Exported Types
  * @{
  */

/**
 *  The handle of DMA
 */
typedef struct
{
    PDMA_TypeDef                *Instance;  /*!< Register base address   */
    HAL_LockTypeDef             Lock;       /*!< DMA locking object      */
    __IO HAL_DMA_State_TypeDef  State;

} HAL_DMA_Handle_TypeDef;

/**
 *  The data structure of a DMA Descriptor
 */
typedef struct DMA_Descriptor
{
    /* Note! Use of double volatile qualifier to ensure that both */
    /* pointer and referenced memory are declared volatile. */
    volatile void* volatile     src_addr_end;  /**< DMA source address end */
    volatile void* volatile     dst_addr_end;  /**< DMA destination address end */
    volatile uint32_t           ctrl;          /**< DMA control register, reference uDMA PL230 documentation */
    volatile uint32_t           user;          /**< DMA padding register, available for user */
} DMA_Descriptor_t;

/**
 *  The configuration of a DMA descriptor
 */
typedef struct HAL_DMA_Descriptor_Cfg
{
    void            *src_addr;
    void            *dst_addr;
    uint32_t        user_data;
    uint16_t        xfer_bytes;     /**< Total transfer bytes, it MUST be case about alignment */
    short           timeout;        /**< the timeout ticks. If timeout < 0, block flow. */

    DMA_Descriptor_Type_t       type;
    HAL_DMA_Mode_TypeDef        mode;

    DMA_Data_Inc_t              src_inc;
    DMA_Data_Inc_t              dst_inc;
    DMA_Data_Size_t             unit_size;
    DMA_Arbitration_Rate_t      arbit_rate;

} HAL_DMA_Descriptor_Cfg_TypeDef;

/**
 *  DMA channel configuration
 */
typedef struct HAL_DMA_Channel_Cfg
{
    union {
        uint32_t    cfg_value;
        struct {
            uint32_t                         : 1;
            uint32_t     is_high_priority    : 1;   /**< use high priority or not */
            uint32_t     is_enable_interrupt : 1;   /**< enable interrupt or not */
            uint32_t     is_peri_trigger     : 1;   /**< Trigger with peripheral or not */
            uint32_t     is_burst_mode       : 1;   /**< use burst mode or not */
            uint32_t     is_channel_switch   : 1;   /**< switch DMA channel (CHSELREQ[C] = 1) or not */
        };
    };
} HAL_DMA_Channel_Cfg_TypeDef;

/**
 *  transfer configuration of DMA
 */
typedef struct HAL_DMA_Xfer_Cfg
{
    uint8_t                 is_immediate;   /**< immediately launch DMA to transfer */
    short                   timeout;        /**< the timeout ticks. If timeout < 0, block flow. */
    DMA_Descriptor_Type_t   type;           /**< use primary or alternate */
    HAL_DMA_Mode_TypeDef    mode;
    uint32_t                user_data;

} HAL_DMA_Xfer_Cfg_TypeDef;

/**
  * @}
  */ /* End of group DMA_Exported_Types */

//=============================================================================
//                  Macro Definition
//=============================================================================
/** @defgroup DMA_Exported_Macros DMA Exported Macros
  * @{
  */


/**
 *  \brief  Monitor requests of a DMA channel
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_WATCH_CHANNEL(__HANDLE__, __CHANNEL__)   \
            ((__HANDLE__)->Instance->CHRMKCLR |= (__CHANNEL__))

/**
 *  \brief  Ignore requests of a DMA channel
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_IGNORE_CHANNEL(__HANDLE__, __CHANNEL__)  \
            ((__HANDLE__)->Instance->CHRMKSET |= (__CHANNEL__))

/**
 *  \brief  Get uDMA PL230 H/w state
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \return
 *      reference DMA_State_t
 */
#define __HAL_DMA_GET_STATE(__HANDLE__) \
            (((__HANDLE__)->Instance->STA & PDMA_STA_STATE_Msk) >> PDMA_STA_STATE_Pos)


/**
 *  \brief  Immediately launch DMA channel with S/w request
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_FORCE_START(__HANDLE__, __CHANNEL__)  \
            ((__HANDLE__)->Instance->CHSWREQ |= (__CHANNEL__))


/**
 *  \brief  Check DMA is error status or not
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \return
 *      0: No error, others: DMA issue error
 */
#define __HAL_DMA_IS_ERROR_STATUS(__HANDLE__)   \
            ((__HANDLE__)->Instance->CHERRCLR & PDMA_CHERRCLR_ERRCLR_Msk)

/**
 *  \brief  Clear DMA error status
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 */
#define __HAL_DMA_CLR_ERROR_STATUS(__HANDLE__)   \
            ((__HANDLE__)->Instance->CHERRCLR = PDMA_CHERRCLR_ERRCLR)

/**
 *  \brief  Enable interrupt when error
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 */
#define __HAL_DMA_ENABLE_ERR_IT(__HANDLE__)                \
            (__HANDLE__)->Instance->CHINTSET |= (PDMA_CHINTSET_ERRINTEN_Msk)

/**
 *  \brief  Disable interrupt when error
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 */
#define __HAL_DMA_DISABLE_ERR_IT(__HANDLE__)               \
            (__HANDLE__)->Instance->CHINTCLR |= (PDMA_CHINTCLR_ERRINTCLR_Msk)

/**
 *  \brief  Check interrupt flag of DMA error
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 */
#define __HAL_DMA_IS_ERR_IRQ(__HANDLE__)   \
            ((__HANDLE__)->Instance->CHTCIF & (PDMA_CHTCIF_ERRIF_Msk))

/**
 *  \brief  Clear IRQ flag of DMA error
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 */
#define __HAL_DMA_CLR_ERR_IRQ_FLAG(__HANDLE__)   \
            ((__HANDLE__)->Instance->CHTCIF |= (PDMA_CHTCIF_ERRIF_Msk))

/**
 *  \brief  Check DMA IRQ flags of channels done
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_IS_CHANNEL_IRQ(__HANDLE__,  __CHANNEL__)   \
            ((__HANDLE__)->Instance->CHTCIF & (__CHANNEL__))


/**
 *  \brief  Clear IRQ flags of DMA hannels
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_CLR_CHANNEL_IRQ_FLAG(__HANDLE__,  __CHANNEL__)   \
            ((__HANDLE__)->Instance->CHTCIF = (__CHANNEL__))

/**
 *  \brief  Enable DMA interrupt
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_ENABLE_IT(__HANDLE__, __CHANNEL__)                \
            (__HANDLE__)->Instance->CHINTSET |= (__CHANNEL__)


/**
 *  \brief  Disable DMA interrupt
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_DISABLE_IT(__HANDLE__, __CHANNEL__)               \
            (__HANDLE__)->Instance->CHINTCLR |= (__CHANNEL__)


/**
 *  \brief  Convert the ctrl member of a descriptor to bytes length
 *              This macro ONLY be used before launch DMA.
 *              ps. DMA processes will modify the ctrl member of a descriptor
 *
 *  \param [in] dma_ctrl        The ctrl member of a descriptor
 *  \return
 *      bytes length in a descriptor
 */
#define __HAL_DMA_CONVERT_TO_BYTES(dma_ctrl)        \
            (((((dma_ctrl) >> 4) & 0x3FFul) + 1) * (0x1ul << (((dma_ctrl) >> 28) & 0x3ul)))


/**
 *  \brief  Get the pointer of a descriptor
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 *  \param [in] __TYPE__        Primary or Alternate type, reference DMA_Descriptor_Type_t
 *  \return
 *      Pointer of the descriptor structure
 */
#define __HAL_DMA_GET_DESCRIPTOR_ADDR(__HANDLE__, __CHANNEL__, __TYPE__)                         \
            ((__TYPE__) == DMA_DESCRIPTOR_TYPE_ALTERNATE)                                        \
            ? &((DMA_Descriptor_t*)(__HANDLE__)->Instance->ADBPTR)[31 - __CLZ((__CHANNEL__))]    \
            : &((DMA_Descriptor_t*)(__HANDLE__)->Instance->PDBPTR)[31 - __CLZ((__CHANNEL__))]

/**
 *  \brief  Set high priority of a channel
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_HIGH_PRIORITY(__HANDLE__, __CHANNEL__)        \
            (__HANDLE__)->Instance->CHPRISET |= (__CHANNEL__)

/**
 *  \brief  Set default priority of a channel
 *
 *  \param [in] __HANDLE__      The pointer of a HAL_DMA_Handle_TypeDef structure
 *  \param [in] __CHANNEL__     DMA channel, reference enum HAL_DMA_Channel
 */
#define __HAL_DMA_DEF_PRIORITY(__HANDLE__, __CHANNEL__)        \
            (__HANDLE__)->Instance->CHPRICLR |= (__CHANNEL__)

/**
  * @}
  */ /* End of group DMA_Exported_Macros */


//=============================================================================
//                  Public Function Definition
//=============================================================================
/** @addtogroup DMA_Exported_Functions
  * @{
  */

/**
 *  @brief  DMA initialize
 *
 *  @param [in] hDMA        pointer to a HAL_DMA_Handle_TypeDef structure
 *  @return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef HAL_DMA_Init(HAL_DMA_Handle_TypeDef *hDMA);

/**
 *  @brief DMA de-initialize
 *
 *  @param [in] hDMA        pointer to a HAL_DMA_Handle_TypeDef structure
 *  @return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef HAL_DMA_DeInit(HAL_DMA_Handle_TypeDef *hDMA);


/**
 *  @brief  DMA configure a data structure
 *
 */

/**
 *  \brief  Configure a descriptor of DMA control
 *              Only support to configure a channel.
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] channal_id      Channel id, reference HAL_DMA_Channel_TypeDef
 *  \param [in] pCfg            The configuration of a descriptor, reference HAL_DMA_Descriptor_Cfg_TypeDef
 *  \param [in] pDesc           Pointer to a DMA_Descriptor_t structure.
 *                                  User provide a private descriptor pool, or set to NULL.
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Set_Descriptor(
    HAL_DMA_Handle_TypeDef          *hDMA,
    HAL_DMA_Channel_TypeDef         channal_id,
    HAL_DMA_Descriptor_Cfg_TypeDef  *pCfg,
    DMA_Descriptor_t                *pDesc);


/**
 *  \brief  Get the descriptor of DMA
 *              This function ONLY be used before launch DMA
 *              ps. DMA processes will modify the ctrl member of a descriptor
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] channal_id      Channel id, reference HAL_DMA_Channel_TypeDef
 *  \param [in] type            Target Primary/Alternate descriptor, reference DMA_Descriptor_Type_t
 *  \param [in] pCfg            The reported configuration of a descriptor, reference HAL_DMA_Descriptor_Cfg_TypeDef
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Get_Descriptor(
    HAL_DMA_Handle_TypeDef          *hDMA,
    HAL_DMA_Channel_TypeDef         channal_id,
    DMA_Descriptor_Type_t           type,
    HAL_DMA_Descriptor_Cfg_TypeDef  *pCfg);

/**
 *  \brief  Configure a channel of DMA
 *              Only support to configure a channel.
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] channal_id      Channel id, reference HAL_DMA_Channel_TypeDef
 *  \param [in] pCfg            The configuration of a channel, reference HAL_DMA_Channel_Cfg_TypeDef
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Set_Channel(
    HAL_DMA_Handle_TypeDef      *hDMA,
    HAL_DMA_Channel_TypeDef     channal_id,
    HAL_DMA_Channel_Cfg_TypeDef *pCfg);


/**
 *  \brief  Start a DMA channel
 *              Only support to start a channel.
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] channal_id      Channel id, reference HAL_DMA_Channel_TypeDef
 *  \param [in] pCfg            The configuration of transfer, reference HAL_DMA_Xfer_Cfg_TypeDef
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Channel_Sart(
    HAL_DMA_Handle_TypeDef      *hDMA,
    HAL_DMA_Channel_TypeDef     channal_id,
    HAL_DMA_Xfer_Cfg_TypeDef    *pCfg);

/**
 *  \brief  Force to stop a channel of DMA
 *              Only support to stop a channel.
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] channal_id      Channel id, reference HAL_DMA_Channel_TypeDef
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Channel_Stop(
    HAL_DMA_Handle_TypeDef      *hDMA,
    HAL_DMA_Channel_TypeDef     channal_id);


/**
 *  \brief  Verify the base address of descriptors pool
 *
 *  \param [in] hDMA            Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \param [in] addr            The address of user descriptors pool
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_DMA_Verify_Descriptor_Base_Addr(
    HAL_DMA_Handle_TypeDef  *hDMA,
    uint32_t                addr);


/**
 *  \brief  ISR of DMA
 *
 *  \param [in] hDMA        Pointer to a HAL_DMA_Handle_TypeDef structure
 *  \return
 *      None
 */
void HAL_DMA_IRQHandler(HAL_DMA_Handle_TypeDef *hDMA);


/**
  * @}
  */ /* End of group DMA_Exported_Functions */

/**
  * @}
  */ /* End of group DMA */

/**
  * @}
  */ /* End of group ZB32L03x_HAL_Driver */


#ifdef __cplusplus
}
#endif

#endif
